type EventMap = {
  [key: string]: any[];
};

class EventEmitter<Events extends EventMap> {
  private events: Partial<Record<keyof Events, any[]>> = {};

  on<K extends keyof Events>(eventName: K, handler: (...args: Events[K]) => void): void {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName]?.push(handler);
  }

  off<K extends keyof Events>(eventName: K, handler: (...args: Events[K]) => void): void {
    const handlers = this.events[eventName];
    if (!handlers) {
      return;
    }
    this.events[eventName] = handlers.filter((h) => h !== handler);
  }

  emit<K extends keyof Events>(eventName: K, ...args: Events[K]): void {
    const handlers = this.events[eventName];
    if (!handlers) {
      return;
    }
    handlers.forEach((handler) => handler(...args));
  }
}

export default EventEmitter;
